package com.wing.common;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Table;
import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.simple.ParameterizedBeanPropertyRowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.stereotype.Repository;

import com.wing.common.util.PageBean;

@Repository
public class CommonSpringJDBC<T, PK extends Serializable> {

	static final Log logger = LogFactory.getLog(CommonSpringJDBC.class);

	private SimpleJdbcTemplate simpleJdbcTemplate;
	protected Class<T> entityClass;
	
//	@Autowired 
//	public void init(){
//		this.entityClass = (Class<T>) ((ParameterizedType) getClass()
//				.getGenericSuperclass()).getActualTypeArguments()[0];
//	}
//	
	public SimpleJdbcTemplate getSimpleJdbcTemplate() {
		return simpleJdbcTemplate;
	}

	@Autowired
	public void setSimpleJdbcTemplate(DataSource dataSource) {
		this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
	}

	public void insert(T entity) {
		logger.info("saving " + entity.toString() + " instance");
		String sql = builderInsertSqlByEntity(entity);
		simpleJdbcTemplate.update(sql, new BeanPropertySqlParameterSource(
				entity));
		logger.info("save successful sql = "+sql);
	}

	public void update(T entity) {
		logger.info("updating " + entity.toString() + " instance");
		String sql = builderUpdateSqlByEntity(entity);
		simpleJdbcTemplate.update(sql, new BeanPropertySqlParameterSource(
				entity));
		logger.info("updaed successful sql = "+sql);
	}

	public void delete(final PK id) {
		String sql = builderDeleteSql();
		simpleJdbcTemplate.update(sql, id);
		logger.info("delete successful sql = " +sql+" ,id = "+id);
	}

	public T findById(final PK id) {
		this.entityClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
		String sql = builderfindByIdSql();
		logger.info("find sql = " +sql+" ,id = "+id);
		return simpleJdbcTemplate
				.queryForObject(sql, ParameterizedBeanPropertyRowMapper
						.newInstance(entityClass), id);
	
		
	}

	public List<Map<String, Object>> findAll() {
		String sql = builderfindAllSql();
		return simpleJdbcTemplate.queryForList(sql);
	}

	//分页的查询方法
	public PageBean findPageList(String[] sqlArray,int currentPage, int pageSize,Object... args) {
		StringBuffer wrapperSql = new StringBuffer();
		
		int allRow = findPageSize(sqlArray[1]); // 总记录数
		List<Map<String, Object>> dataList = simpleJdbcTemplate.queryForList(sqlArray[0],args);
		
		int totalPage = PageBean.countTotalPage(pageSize, allRow); // 总页数
		PageBean pageBeanDaoImpl = new PageBean();
		pageBeanDaoImpl.setPageSize(pageSize);
		pageBeanDaoImpl.setCurrentPage(currentPage);
		pageBeanDaoImpl.setAllRow(allRow);
		pageBeanDaoImpl.setTotalPage(totalPage);
		pageBeanDaoImpl.setRecordList(dataList);
		pageBeanDaoImpl.init();
		return pageBeanDaoImpl;
		
	}
	
	public int findPageSize(String sql_count) {
		StringBuffer wrapperSql = new StringBuffer();
		return simpleJdbcTemplate.queryForInt(sql_count);
	}
	
	// 创建新增sql
	private String builderInsertSqlByEntity(T entity) {
		StringBuffer sb = new StringBuffer();
		String tabName = findTabnameByEntity();
		Map<String, String> colAndField = findFieldByColumnAnnotation(entity);
		StringBuffer colStrings = new StringBuffer();
		StringBuffer fieldStrings = new StringBuffer();
		colStrings.append(" (");
		fieldStrings.append(" (");
		for (String dataKey : colAndField.keySet()) {
			colStrings.append(dataKey).append(",");
			fieldStrings.append(":").append((colAndField.get(dataKey))).append(
					",");
		}
		sb.append("insert into ").append(tabName).append(
				colStrings.toString().substring(0,
						colStrings.toString().length() - 1));
		sb.append(")");
		sb.append(" values ");
		sb.append(fieldStrings.toString().substring(0,
				fieldStrings.toString().length() - 1));
		sb.append(")");
		return sb.toString();
	}

	// 创建更新sql
	private String builderUpdateSqlByEntity(T entity) {
		StringBuffer sb = new StringBuffer();
		String tabName = findTabnameByEntity();
		Map<String, String> colAndField = findFieldByColumnAnnotation(entity);
		Map<String, String> keyMap = findKeyFieldByColumnAnnotation();
		StringBuffer colStrings = new StringBuffer();
		for (String dataKey : colAndField.keySet()) {
			if(dataKey.equals(keyMap.get("colName"))){continue;}
			colStrings.append(dataKey).append(" = :").append(colAndField.get(dataKey)).append(",");
		}
		sb.append("update ").append(tabName).append(" set ");
		sb.append(colStrings.toString().substring(0,
				colStrings.toString().length() - 1));
		sb.append("  where ");
		sb.append(keyMap.get("colName"));
		sb.append("  =  :").append(keyMap.get("fieldName"));
		return sb.toString();
	}

	// 创建更新sql
	private String builderDeleteSql() {
		StringBuffer sb = new StringBuffer();
		String tabName = findTabnameByEntity();
		Map<String, String> keyMap = findKeyFieldByColumnAnnotation();
		sb.append("delete from ").append(tabName);
		sb.append("  where ");
		sb.append(keyMap.get("colName"));
		sb.append("  =  ? ");
		return sb.toString();
	}

	// 创建查找一个对象sql
	private String builderfindByIdSql() {
		StringBuffer sb = new StringBuffer();
		String tabName = findTabnameByEntity();
		Map<String, String> keyMap = findKeyFieldByColumnAnnotation();
		sb.append("select * from ").append(tabName);
		sb.append("  where ");
		sb.append(keyMap.get("colName"));
		sb.append("  =  ? ");
		return sb.toString();
	}

	// 创建查找一个对象sql
	private String builderfindAllSql() {
		StringBuffer sb = new StringBuffer();
		String tabName = findTabnameByEntity();
		Map<String, String> keyMap = findKeyFieldByColumnAnnotation();
		sb.append("select * from ").append(tabName);
		return sb.toString();
	}

	// 通过注解查找表名
	private String findTabnameByEntity() {
		this.entityClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
		Annotation[] annotations = entityClass.getDeclaredAnnotations();
		for (Annotation an : annotations) {
			if (an.annotationType().getSimpleName().equals("Table")) {
				return ((Table) an).name();
			}
		}
		return "域对象没有定义@Table";
	}

	// 根据注解获得表列名
	private Map<String, String> findFieldByColumnAnnotation(T entity) {
		Map<String, String> colAndField = new HashMap<String, String>();
		Field[] fields = entity.getClass().getDeclaredFields();
		for (Field f : fields) {
			Annotation[] fileNnnotations = f.getAnnotations();
			for (Annotation an : fileNnnotations) {
				if (an.annotationType().getSimpleName().equals("Column")) {
					colAndField.put(((Column) an).name(), f.getName());
				}
			}
		}
		return colAndField;
	}

	// 根据注解获得表的主键列名和对应属性
	private Map<String, String> findKeyFieldByColumnAnnotation() {
		Map<String, String> keyMap = new HashMap<String, String>();
		this.entityClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
		Field[] fields = entityClass.getDeclaredFields();
		for (Field f : fields) {
			String colName = "";
			boolean isKey = false;
			Annotation[] fileNnnotations = f.getAnnotations();
			for (Annotation an : fileNnnotations) {
				if (an.annotationType().getSimpleName().equals("Column")) {
					colName = ((Column) an).name();
				}
				if (an.annotationType().getSimpleName().equals("Id")) {
					isKey = true;
				}
			}
			if (isKey) {
				keyMap.put("colName", colName);
				keyMap.put("fieldName", f.getName());
				return keyMap;
			}
		}
		return keyMap;
	}
}
